package process

import (
	"communication-system/common/message"
	"communication-system/server/utils"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"os"
)

type UserProcess struct {
}

func (this *UserProcess) Register(userId int, userPwd string, userName string) (err error) {
	//1.connect to server
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err=", err)
		return
	}
	defer conn.Close()
	//2. ready to send Msg to server
	var mes message.Message
	mes.Type = message.RegisterMesType
	//3. create a struct of RegisterMes
	var registerMes message.RegisterMes
	registerMes.User.UserId = userId
	registerMes.User.UserPwd = userPwd
	registerMes.User.UserName = userName
	//4. registerMes serialize
	data, err := json.Marshal(registerMes)
	if err != nil {
		fmt.Println("json.Marshal err=", err)
		return
	}
	//5. data --> mes.Data
	mes.Data = string(data)
	//6. mes serialize
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("json.Marshal err=", err)
		return
	}
	//deal with msg from server
	tf := &utils.Transfer{
		Conn: conn,
	}
	//send data to server
	err = tf.WritePkg(data)
	if err != nil {
		fmt.Println("signin err=", err)
		return
	}

	mes, err = tf.ReadPkg() //mes = RegisterResMes
	if err != nil {
		fmt.Println("readPkg(conn) err=", err)
		return
	}

	var registerResMes message.RegisterResMes
	err = json.Unmarshal([]byte(mes.Data), &registerResMes)
	if registerResMes.Code == 200 {
		fmt.Println("SignIn success, Please Login again")
		os.Exit(0)
	} else {
		fmt.Println(registerResMes.Error)
		os.Exit(0)
	}
	return
}

//login
func (this *UserProcess) Login(userId int, userPwd string) (err error) {
	//1.connect to server
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err=", err)
		return
	}
	defer conn.Close()
	//2. ready to send Msg to server
	var mes message.Message
	mes.Type = message.LoginMesType
	//3. create a struct of LoginMes
	var loginMes message.LoginMes
	loginMes.UserId = userId
	loginMes.UserPwd = userPwd
	//4. loginMes serialize
	data, err := json.Marshal(loginMes)
	if err != nil {
		fmt.Println("json.Marshal err=", err)
		return
	}
	//5. data --> mes.Data
	mes.Data = string(data)
	//6. mes serialize
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("json.Marshal err=", err)
		return
	}
	//7. data is the data that we want to send
	var pkgLen uint32 //get the len of data -> transform a slice for expressing len
	pkgLen = uint32(len(data))
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[:4], pkgLen)
	//send len
	n, err := conn.Write(buf[0:4])
	if n != 4 || err != nil {
		fmt.Println("conn.Write(bytes) fail=", err)
		return
	}
	fmt.Printf("client send PkgLen is=%d comment=%s\n", len(data), string(data))

	//send msg
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println("conn.Write(data) fail=", err)
		return
	}
	//deal with msg from server
	tf := &utils.Transfer{
		Conn: conn,
	}
	mes, err = tf.ReadPkg()
	if err != nil {
		fmt.Println("readPkg(conn) err=", err)
		return
	}
	var loginResMes message.LoginResMes
	err = json.Unmarshal([]byte(mes.Data), &loginResMes)
	if loginResMes.Code == 200 {
		//init CurUser
		CurUser.Conn = conn
		CurUser.UserId = userId
		CurUser.UserStatus = message.UserOnline
		//fmt.Println("login success")
		//show onlineusers
		fmt.Println("Online users as follow:")
		for _, v := range loginResMes.UserId {
			if v == userId {
				continue
			}
			fmt.Println("userId:\t", v)
			//client onlineUser init
			user := &message.User{
				UserId:     v,
				UserStatus: message.UserOnline,
			}
			onlineUsers[v] = user
		}
		fmt.Println()
		fmt.Println()
		//keep the connect with server, recv the msg from server
		go serverProcessMes(conn)

		//1. show the menu of success login(loop)
		for {
			ShowMenu()
		}
	} else {
		fmt.Println(loginResMes.Error)
	}
	return
}
